import json
import os
import time
import zipfile
import random
from datetime import datetime, timedelta

# ==================== 配置参数 ====================
# 作业归属人
OWNER = 'guoziqing'
# 作业归属目录
DIRECTORY = '/PRD/PRD_SDI/ICS'
# 调度集群名称
CLUSTER_NAME = 'cdm-hq04'
# 输入文件路径
INPUT_FILE_PATH = r"C:\Users\Administrator\Desktop\大唐数科\一体化定时任务.txt"
# 模板文件路径
TEMPLATE_FILE_PATH = "SDI导入调度作业/sdi导入任务调度template模板.json"
# 输出目录
OUTPUT_DIR = "../job_directory"
# ZIP文件输出路径
ZIP_OUTPUT_PATH = "../job_zip/job.zip"
# 已存在的作业文件目录（用于查找依赖任务的时间）
EXISTING_JOBS_DIR = "../existing_jobs"  # 存放已有job文件的目录
# 时间增量（分钟）
TIME_INCREMENT_MINUTES = 15
# ================================================

def parse_cron_expression(expression):
    """
    解析cron表达式，返回小时和分钟
    """
    parts = expression.split()
    if len(parts) >= 3:
        second = int(parts[0]) if parts[0].isdigit() else 0
        minute = int(parts[1]) if parts[1].isdigit() else 0
        hour = int(parts[2]) if parts[2].isdigit() else 0
        return hour, minute, second
    return 0, 0, 0

def calculate_new_time_from_dependency(dependency_job_name):
    """
    根据依赖任务计算新的调度时间
    """
    # 查找依赖任务的配置文件
    dependency_file_path = None

    # 在输出目录中查找
    for file in os.listdir(OUTPUT_DIR):
        if file.endswith('.job') and dependency_job_name in file:
            dependency_file_path = os.path.join(OUTPUT_DIR, file)
            break

    # 如果在输出目录没找到，则在已存在作业目录中查找
    if not dependency_file_path and os.path.exists(EXISTING_JOBS_DIR):
        for file in os.listdir(EXISTING_JOBS_DIR):
            if file.endswith('.job') and dependency_job_name in file:
                dependency_file_path = os.path.join(EXISTING_JOBS_DIR, file)
                break

    if dependency_file_path and os.path.exists(dependency_file_path):
        try:
            with open(dependency_file_path, 'r', encoding='utf8') as f:
                dependency_config = json.load(f)
                cron_expr = dependency_config['schedule']['cron']['expression']
                dep_hour, dep_minute, dep_second = parse_cron_expression(cron_expr)

                # 计算新时间（在依赖任务时间基础上增加指定分钟数）
                dep_time = datetime(2025, 1, 1, dep_hour, dep_minute, dep_second)
                new_time = dep_time + timedelta(minutes=TIME_INCREMENT_MINUTES)

                # 处理跨天情况
                new_time = new_time.time()
                return new_time.hour, new_time.minute, new_time.second
        except Exception as e:
            print(f"解析依赖任务 {dependency_job_name} 时间出错: {e}")

    # 如果找不到依赖任务或出错，则使用随机时间
    hour = random.randint(4, 6)
    minute = random.randint(0, 59)
    second = random.randint(0, 59)
    return hour, minute, second

def generate_job_files():
    """
    根据输入文件生成作业配置文件
    """
    start_time = time.strftime('%Y-%m-%dT%H:%M:%S+08')

    with open(INPUT_FILE_PATH, 'r', encoding='utf8') as input_file:
        line = input_file.readline()
        while line != '':
            strs = line.replace("\n", "").split("\t")
            task_name = strs[0]
            sdi_task = strs[1]

            # 获取依赖任务（如果有）
            dependency_task = strs[2] if len(strs) > 2 and strs[2].strip() else None

            # 生成调度时间
            if dependency_task:
                # 根据依赖任务计算时间
                hour, minute, second = calculate_new_time_from_dependency(dependency_task)
            else:
                # 无依赖任务，使用随机时间
                hour = random.randint(4, 6)
                minute = random.randint(0, 59)
                second = random.randint(0, 59)

            # 创建输出文件路径
            output_file_path = os.path.join(OUTPUT_DIR, f"{task_name}.job")

            # 读取模板并生成作业文件
            with open(output_file_path, "w", encoding='utf8') as out:
                with open(TEMPLATE_FILE_PATH, "r", encoding='utf8') as template_file:
                    jsonobj = json.load(template_file)
                    # 更新基本配置
                    jsonobj['basicConfig']['owner'] = OWNER
                    jsonobj['directory'] = DIRECTORY
                    jsonobj['name'] = task_name

                    # 更新节点配置
                    node = jsonobj['nodes'][0]
                    node['name'] = sdi_task
                    properties = node['properties']
                    properties.append({"name": "clusterName", "value": CLUSTER_NAME})
                    properties.append({"name": "jobName", "value": sdi_task})

                    # 更新调度配置
                    jsonobj['schedule']['cron']['expression'] = f"{second} {minute} {hour} * * ?"
                    jsonobj['schedule']['cron']['startTime'] = start_time

                    # 如果有依赖任务，添加到依赖配置中
                    if dependency_task:
                        jsonobj['schedule']['cron']['dependJobs']['jobs'].append({
                            "jobName": dependency_task,
                            "workspaceName": ""  # 可根据需要设置工作空间名称
                        })

                    # 写入输出文件
                    json.dump(jsonobj, out, ensure_ascii=False, indent=2)

            line = input_file.readline()

def create_zip_archive():
    """
    将生成的作业文件打包成ZIP文件
    """
    with zipfile.ZipFile(ZIP_OUTPUT_PATH, 'w', zipfile.ZIP_DEFLATED) as zip_file:
        files = os.listdir(OUTPUT_DIR)
        for file in files:
            file_path = os.path.join(OUTPUT_DIR, file)
            # 使用相对路径存储文件
            arc_name = os.path.relpath(file_path, os.getcwd())
            zip_file.write(file_path, arc_name)

def main():
    """
    主函数
    """
    # 确保输出目录存在
    os.makedirs(OUTPUT_DIR, exist_ok=True)
    os.makedirs(os.path.dirname(ZIP_OUTPUT_PATH), exist_ok=True)

    # 生成作业文件
    generate_job_files()

    # 创建ZIP归档
    create_zip_archive()

if __name__ == "__main__":
    main()
